
// === uuMeta.image ===
// depend: uuMeta
/*
uuMeta.image.load(url, callback)
uuMeta.image.getActualDimension(image) - return { w, h }
 */
(function uuMetaImageScope() {
var _mm = uuMeta,
    _cache = {}; // { url: Image, ... }

// uuMeta.image.load - delay loader
function load(url,        // @param String:
              callback) { // @param Function: callback(img, state, dim)
                          //     Object: image object
                          //     Number: state, 0(loading...),
                          //                    1(loaded), -1(error)
                          //     Hash: dim: { w, h }
                          // @return Image: image object
  function calls() {
    var v, i = 0, ary = _mm.toArray(img.callback),
        // keep objects
        ki = img, ks = img.state,
        kdim = { w: img.width, h: img.height };

    img.callback = []; // clear
    while ( (v = ary[i++]) ) {
      try {
        v(ki, ks, kdim);
      } catch(err) {}
    }
  }

  var img;

  if (url in _cache) {
    img = _cache[url];
    img.callback.push(callback); // stock
    img.state && calls(); // -1 or 1
    return img;
  }

  _cache[url] = img = new Image();

  img.state = 0; // bond
  img.clear = function() { // bond
    delete _cache[url];
    img.onerror = img.onload = "";
    img = void 0; // fix memory leak in IE6
  };
  img.onerror = function() {
    img.state = -1; // error
    img.width = img.height = 0;
    calls();
  };
  img.onload = function() {
    if (img.complete ||
        img.readyState === "complete") { // IE8
      img.state = 1; // loaded
      calls();
    }
  };
  !("callback" in img) && (img.callback = []); // bond
  img.callback.push(callback); // stock
  img.setAttribute("src", url);
  return img;
}

// uuMeta.image.getActualDimension
// http://d.hatena.ne.jp/uupaa/20090602
function getActualDimension(image) { // @param HTMLImageElement
                                     // @return Hash: { w, h }
  var run, mem, w, h, key = "actual";

  // for Firefox, Safari, Chrome
  if ("naturalWidth" in image) {
    return { w: image.naturalWidth, h: image.naturalHeight };
  }

  if ("src" in image) { // HTMLImageElement
    if (image[key] && image[key].src === image.src) {
      return image[key];
    }
    if (_mm.ua.ie) { // for IE
      run = image.runtimeStyle;
      mem = { w: run.width, h: run.height }; // keep runtimeStyle
      run.width  = "auto"; // override
      run.height = "auto";
      w = image.width;
      h = image.height;
      run.width  = mem.w; // restore
      run.height = mem.h;
    } else { // for Opera
      mem = { w: image.width, h: image.height }; // keep current style
      image.removeAttribute("width");
      image.removeAttribute("height");
      w = image.width;
      h = image.height;
      image.width  = mem.w; // restore
      image.height = mem.h;
    }
    return image[key] = { w: w, h: h, src: image.src }; // bond
  }
  // HTMLCanvasElement
  return { w: image.width, h: image.height };
}

// --- initialize ---

// --- export ---
_mm.image = {
  load: load,
  getActualDimension: getActualDimension
};

})(); // uuMeta.image scope

